1 00:00:00,390 --> 00:00:01,230 Hey there! 2 00:00:01,230 --> 00:00:05,160 This lecture is going to discuss a slightly more advanced topic. 3 00:00:05,160 --> 00:00:11,130 We are going to explore coroutines, and a coroutine is created by the coroutine library, and a coroutine 4 00:00:11,130 --> 00:00:14,520 is represented by a data type in Lua called a thread. 5 00:00:14,520 --> 00:00:19,950 Now the thread data type doesn't actually represent what we would think of as a processor thread. 6 00:00:19,950 --> 00:00:25,320 The creators of Lua just gave it the name of thread, but it isn't actually a processor thread. 7 00:00:25,350 --> 00:00:26,640 I know it's confusing. 8 00:00:26,640 --> 00:00:32,130 Instead, a coroutine is a function or a block of code that can have its flow manipulated. 9 00:00:32,130 --> 00:00:36,270 Coroutines allow us to execute multiple tasks within the same script. 10 00:00:36,270 --> 00:00:42,210 In fact, all code executed in your game is handled by different coroutine threads, which are having 11 00:00:42,210 --> 00:00:45,330 their flow manipulated behind the scenes in the game engine. 12 00:00:45,330 --> 00:00:51,840 When we have code in a script, all of the code inside of the script is being executed from one coroutine 13 00:00:51,840 --> 00:00:52,350 thread. 14 00:00:52,350 --> 00:00:55,440 Every script in your game has its own coroutine. 15 00:00:55,440 --> 00:01:01,740 The problem with this is that if we have a while loop that executes infinitely, any code below the 16 00:01:01,740 --> 00:01:03,750 while loop will never execute. 17 00:01:03,750 --> 00:01:08,910 And that's because the main thread of execution is currently busy and it's stuck working inside of the 18 00:01:08,910 --> 00:01:09,540 while loop. 19 00:01:09,540 --> 00:01:14,790 Even if we hit a yield statement inside of the while loop, the current processor thread will just move 20 00:01:14,790 --> 00:01:17,640 to the next coroutine that needs to be executed. 21 00:01:17,640 --> 00:01:23,490 And since all of the code inside of our script is being executed on the same coroutine, the code below 22 00:01:23,490 --> 00:01:25,410 our while loop will never execute. 23 00:01:25,410 --> 00:01:27,750 It's not in a separate coroutine thread. 24 00:01:27,750 --> 00:01:33,390 If you hear me, use the terms current thread or current processor thread or main thread of execution. 25 00:01:33,390 --> 00:01:39,120 I am referring to the actual processor thread that is being fed instructions by the Lua interpreter. 26 00:01:39,120 --> 00:01:44,340 If you are confused by any of this terminology, I have a cheat sheet document at the end of this section 27 00:01:44,340 --> 00:01:47,460 that you can use to understand these terms more clearly. 28 00:01:47,460 --> 00:01:49,110 Now back to our while loop. 29 00:01:49,110 --> 00:01:53,250 We are able to use the coroutine library to create a new coroutine thread. 30 00:01:53,250 --> 00:01:59,820 That way we can split this while loop into a separate coroutine and have more than one coroutine executing 31 00:01:59,820 --> 00:02:04,920 inside of our script, and this gives us the ability to control the flow of these coroutine threads. 32 00:02:04,920 --> 00:02:08,190 So I'm going to place this while loop in a separate coroutine thread. 33 00:02:08,190 --> 00:02:12,120 Don't worry what I'm doing right now, because you're going to learn how to do this in just a bit. 34 00:02:12,120 --> 00:02:15,570 But I'm going to use a function in the coroutine library called create. 35 00:02:15,570 --> 00:02:17,760 And I need to pass a function to it. 36 00:02:17,760 --> 00:02:20,130 And I'm going to place my while loop inside of there. 37 00:02:20,130 --> 00:02:23,070 And this is going to return to me my thread data type. 38 00:02:23,070 --> 00:02:27,240 Then I'm going to go ahead and start this coroutine by using a function called resume. 39 00:02:27,240 --> 00:02:28,920 And I'm going to pass my thread. 40 00:02:28,920 --> 00:02:32,820 And now my while loop is executing in a separate coroutine thread. 41 00:02:32,820 --> 00:02:35,610 So the code in here is in its own coroutine thread. 42 00:02:35,610 --> 00:02:39,000 And the code down here is also in its own coroutine thread. 43 00:02:39,000 --> 00:02:45,480 Since we now have more than one coroutine when the yield statement is reached inside of our first coroutine 44 00:02:45,480 --> 00:02:50,580 thread, the main thread of execution is able to go down and execute the code below the while loop. 45 00:02:50,580 --> 00:02:54,540 Because this code is existing in a different coroutine. 46 00:02:54,540 --> 00:03:00,240 Now, I don't expect you to use coroutines that often in studio, as they can be difficult to debug. 47 00:03:00,240 --> 00:03:05,940 And there are other alternatives that are more user friendly, like the task library, which we're going 48 00:03:05,940 --> 00:03:07,920 to see in a future lecture. 49 00:03:09,020 --> 00:03:14,090 Inside of the Roblox documentation, we are able to read what exactly a coroutine is, and it tells 50 00:03:14,090 --> 00:03:19,550 us that a coroutine is used to perform multiple tasks at the same time from within the same script. 51 00:03:19,550 --> 00:03:25,730 So what I just discussed such tasks might include producing values from inputs or performing work on 52 00:03:25,730 --> 00:03:26,660 a subroutine. 53 00:03:26,660 --> 00:03:32,570 When solving a larger problem, a task doesn't even need to have a defined ending point, but it does 54 00:03:32,570 --> 00:03:38,120 need to define particular times at which it yields or pause to let other things be worked on. 55 00:03:38,120 --> 00:03:43,760 So, as I discussed earlier in our while loop, the code below the while loop won't execute until the 56 00:03:43,760 --> 00:03:49,790 coroutine that is currently using the main thread of execution to execute code yields or pauses. 57 00:03:49,790 --> 00:03:55,460 And as we saw in our example, that yield statement was the task dot wait function, and it tells us 58 00:03:55,460 --> 00:04:00,410 that a new coroutine can be created by providing a function to the coroutine dot create function. 59 00:04:00,410 --> 00:04:06,740 Once created, a coroutine doesn't begin running until the first call to the coroutine dot resume function, 60 00:04:06,740 --> 00:04:09,140 which passes the arguments to the function. 61 00:04:09,140 --> 00:04:15,980 This call returns when the function either halts or calls coroutine dot yield, and when this happens, 62 00:04:15,980 --> 00:04:22,010 coroutine dot resume returns either the values returned by the function, the values sent to coroutine 63 00:04:22,010 --> 00:04:24,050 dot yield, or an error message. 64 00:04:24,050 --> 00:04:28,400 If it does error, the second return value is the thrown error. 65 00:04:28,520 --> 00:04:35,780 Now a coroutine has four different states suspended, running normal, and dead. 66 00:04:35,780 --> 00:04:40,880 When you first create a coroutine using the coroutine dot create function, the thread is going to be 67 00:04:40,880 --> 00:04:46,100 in a suspended state, and then when you start the coroutine or resume it, then it's going to be placed 68 00:04:46,100 --> 00:04:47,600 in the running state. 69 00:04:47,600 --> 00:04:52,160 If the coroutine yields, then it'll go back to being suspended. 70 00:04:52,160 --> 00:04:58,370 And when a coroutine finally finishes executing code, or it returns, or maybe it encounters an error, 71 00:04:58,370 --> 00:05:02,720 then the coroutine is going to be placed in a dead state and it can't be used anymore. 72 00:05:02,750 --> 00:05:08,360 The normal state is going to be when a coroutine gives up control over the main thread of execution, 73 00:05:08,360 --> 00:05:13,280 and resumes a different coroutine thread, and it's waiting for that one to yield. 74 00:05:13,280 --> 00:05:17,090 So let's go ahead and take a look at the different functions within the coroutine library. 75 00:05:17,090 --> 00:05:23,030 For example, this first one is called coroutine dot close and you have to pass to it a coroutine thread 76 00:05:23,030 --> 00:05:29,270 and it says closes and puts the provided coroutine in a dead state, so it closes out or stops the execution 77 00:05:29,270 --> 00:05:30,530 within a coroutine. 78 00:05:30,530 --> 00:05:35,210 The next one here is called create and it says creates a new coroutine with body f. 79 00:05:35,210 --> 00:05:40,490 So we have to pass a function to the create function in order to create a new coroutine thread. 80 00:05:40,610 --> 00:05:43,910 There's a function called is yield able and it says returns true. 81 00:05:43,910 --> 00:05:47,630 If the coroutine this function is called within can safely yield. 82 00:05:47,630 --> 00:05:51,380 So you can call this function whenever inside of any coroutine thread. 83 00:05:51,380 --> 00:05:52,910 And it's going to return a boolean. 84 00:05:52,910 --> 00:05:58,610 If the coroutine can yield, there is another function called coroutine dot resume and it says starts 85 00:05:58,610 --> 00:06:01,850 or continues the execution of coroutine Co. 86 00:06:01,850 --> 00:06:07,640 So we pass a coroutine thread to this and then we can pass any other arguments to that particular coroutine. 87 00:06:07,730 --> 00:06:12,050 We have a function called coroutine dot running and it says returns the running coroutine. 88 00:06:12,050 --> 00:06:16,370 So whenever your code is executing, if you want it to grab the current coroutine thread, you can just 89 00:06:16,370 --> 00:06:20,390 call coroutine dot running and it'll return that value to you. 90 00:06:20,950 --> 00:06:26,530 We have a function called coroutine status and it says returns the status of a coroutine as a string. 91 00:06:26,530 --> 00:06:28,030 So we pass our coroutine. 92 00:06:28,030 --> 00:06:33,280 And then it's going to tell us whether or not the coroutine is suspended, if it's running, if it's 93 00:06:33,280 --> 00:06:35,830 in the normal state, or if it's in the dead state. 94 00:06:36,100 --> 00:06:41,440 The next function we have is called wrap and it says creates a new coroutine and returns a function 95 00:06:41,440 --> 00:06:44,110 that, when called, resumes the coroutine. 96 00:06:44,110 --> 00:06:49,390 So we pass a function to the wrap function and it returns to us another function. 97 00:06:49,390 --> 00:06:53,800 And we are able to call this function to start the execution of the coroutine. 98 00:06:53,800 --> 00:06:57,520 So this does not return a thread data type, but another function. 99 00:06:57,520 --> 00:07:03,010 And because we can just call that function to resume the coroutine, this means we don't have to use 100 00:07:03,010 --> 00:07:04,900 the coroutine dot resume function. 101 00:07:04,900 --> 00:07:10,510 And the last but not least is the coroutine dot yield function, and it says suspends the execution 102 00:07:10,510 --> 00:07:11,500 of the coroutine. 103 00:07:11,500 --> 00:07:14,260 And we're able to pass other information to this function. 104 00:07:14,260 --> 00:07:18,730 So let's go ahead and take a look at all of these different functions in action in Roblox Studio. 105 00:07:19,150 --> 00:07:25,150 So with our first example here I used the coroutine dot create function and passed a function to it 106 00:07:25,150 --> 00:07:30,670 that contained our while loop, and it returned to us a coroutine thread, which is going to execute 107 00:07:30,670 --> 00:07:34,120 this block of code in a separate coroutine. 108 00:07:34,120 --> 00:07:39,640 And then to start this coroutine thread, we have to pass it to the coroutine dot resume function. 109 00:07:39,640 --> 00:07:41,920 So now this while loop will start executing. 110 00:07:42,310 --> 00:07:45,280 Now what I'm going to do is I'm going to put a print statement in here. 111 00:07:45,280 --> 00:07:47,650 I'm going to call this start execution. 112 00:07:48,850 --> 00:07:54,250 Or we could just say, actually, you know, let's put a message in here while loop doing stuff. 113 00:07:54,280 --> 00:07:56,380 The while loop is doing whatever it needs to do. 114 00:07:56,380 --> 00:08:00,490 And then once we hit this yield statement, it'll go back down to this code and execute it and print 115 00:08:00,490 --> 00:08:01,690 it in the console. 116 00:08:01,690 --> 00:08:05,920 So this statement should print first and then this statement should print first. 117 00:08:05,920 --> 00:08:12,250 If I moved this yield statement above the print statement then this will actually print first. 118 00:08:12,250 --> 00:08:14,080 And then this will print second. 119 00:08:14,080 --> 00:08:18,280 Because if you think about it the main thread of execution is going to go in here, create this new 120 00:08:18,280 --> 00:08:20,200 coroutine thread and then we're told to resume it. 121 00:08:20,200 --> 00:08:22,930 So the current thread of execution is going to hop in here. 122 00:08:22,930 --> 00:08:24,280 It'll go into the while loop. 123 00:08:24,280 --> 00:08:28,630 And then it'll immediately hit our yield statement and be like oh well, it's time for me to leave. 124 00:08:28,630 --> 00:08:30,760 Let's see if there's anything else that needs to be executed. 125 00:08:30,760 --> 00:08:36,040 And since our code down here is waiting to execute because it's in a separate coroutine thread, then 126 00:08:36,040 --> 00:08:38,110 the main thread is going to print hi in the console. 127 00:08:38,110 --> 00:08:43,150 And once this yield statement up here is over, it'll come back and print this in the console. 128 00:08:43,150 --> 00:08:44,680 If we flip it around. 129 00:08:45,160 --> 00:08:48,610 Now what's going to happen is the main thread of execution is going to encounter this statement. 130 00:08:48,610 --> 00:08:50,410 It's going to print it into the console. 131 00:08:50,410 --> 00:08:53,260 Then it'll yield and print this in the console. 132 00:08:53,260 --> 00:08:55,300 So let's go ahead and run this game. 133 00:08:56,290 --> 00:09:01,420 And if we take a look at the messages in the console we get while loop doing stuff, then hi. 134 00:09:01,420 --> 00:09:06,640 And then you can see our while loop continuing to do more stuff multiple times every single second. 135 00:09:07,120 --> 00:09:13,840 Now if I move the position of the yield statement above, then we should see hi print first and then 136 00:09:13,840 --> 00:09:16,000 while loop doing stuff will print second. 137 00:09:16,030 --> 00:09:17,920 So let's go ahead and run. 138 00:09:20,630 --> 00:09:22,370 And there we go, high printed first. 139 00:09:22,370 --> 00:09:25,970 Then we get our print statements of while loop doing stuff. 140 00:09:26,730 --> 00:09:30,540 Let's go ahead and take a look at another example of using coroutines. 141 00:09:30,570 --> 00:09:33,270 Let's go ahead and create a new coroutine thread. 142 00:09:33,270 --> 00:09:37,740 So we'll refer to the coroutine library and use the dot create function. 143 00:09:37,740 --> 00:09:39,750 And we need to pass a function to it. 144 00:09:39,750 --> 00:09:42,690 So we'll create an anonymous function here. 145 00:09:42,960 --> 00:09:48,300 And inside of this function I'm going to do is have a for loop that iterates five times. 146 00:09:49,350 --> 00:09:54,960 And what we'll do inside of this for loop is we're going to call the coroutine dot yield function. 147 00:09:55,900 --> 00:10:00,460 And what we're going to do is we're going to pass AI to this function call. 148 00:10:00,700 --> 00:10:07,030 And then once this for loop is done executing at the end, we're going to return a message like finished. 149 00:10:07,850 --> 00:10:11,210 So now this is going to return to us a thread data type. 150 00:10:11,660 --> 00:10:18,500 And we need to use the coroutine dot resume function to start executing the code inside of this thread. 151 00:10:18,950 --> 00:10:25,790 So we can go ahead and call coroutine dot resume and pass the thread here. 152 00:10:26,300 --> 00:10:31,190 Now what's going to happen is that the main thread of execution is going to go through here. 153 00:10:31,190 --> 00:10:34,130 And it's going to start this thread and it's going to go in. 154 00:10:34,130 --> 00:10:38,570 And the first statement is going to execute is this coroutine dot yield function call. 155 00:10:38,570 --> 00:10:40,160 And we're passing I to it. 156 00:10:40,160 --> 00:10:41,420 What is that going to do. 157 00:10:41,450 --> 00:10:44,060 Well it's going to force this coroutine to yield. 158 00:10:44,060 --> 00:10:49,610 And we're going to return back to our coroutine dot resume function call with this value. 159 00:10:49,610 --> 00:10:55,250 So that means what is going to be returned from the coroutine dot resume function is going to be our 160 00:10:55,250 --> 00:10:56,690 value of I. 161 00:10:56,720 --> 00:11:01,010 But there is also going to be another value that is returned from the coroutine resume function. 162 00:11:01,010 --> 00:11:02,210 And that's a boolean. 163 00:11:02,210 --> 00:11:05,000 So let's first make a variable for the boolean. 164 00:11:05,000 --> 00:11:08,660 And then we're also able to grab our number I. 165 00:11:08,660 --> 00:11:11,330 And then we can print this out inside of the console. 166 00:11:11,330 --> 00:11:13,640 So we'll print bool and I. 167 00:11:13,640 --> 00:11:18,740 If we go ahead and run the game and we take a look in the console, we're going to get true. 168 00:11:18,740 --> 00:11:23,480 And then our first index in that for loop which is the number one. 169 00:11:23,870 --> 00:11:29,600 Now our coroutine is not going to continue executing this for loop until we are explicitly told to resume 170 00:11:29,600 --> 00:11:32,870 this coroutine, again using our coroutine dot resume function. 171 00:11:32,870 --> 00:11:38,690 Now you might be wondering what this boolean represents, and the boolean represents whether or not 172 00:11:38,690 --> 00:11:40,940 our coroutine encountered an error. 173 00:11:40,940 --> 00:11:45,980 And that's because coroutines are automatically protected when they encounter an error. 174 00:11:45,980 --> 00:11:50,630 If a coroutine does encounter an error, then this boolean is going to be set to false. 175 00:11:50,630 --> 00:11:55,970 And the second argument is going to be the error message or whatever happened that caused the coroutine 176 00:11:55,970 --> 00:11:59,150 to halt execution, which is what we read in the documentation. 177 00:11:59,600 --> 00:12:05,690 Now, to be able to execute this coroutine fully, I need to call my coroutine dot resume function five 178 00:12:05,720 --> 00:12:09,560 times, because I'm yielding through every iteration of our for loop. 179 00:12:09,560 --> 00:12:12,230 So let's go ahead and make a repeat loop down here. 180 00:12:12,230 --> 00:12:19,160 And we're going to repeatedly call our coroutine dot resume function on this particular coroutine thread. 181 00:12:19,160 --> 00:12:25,160 And then we're also able to print out the results from the coroutine resume function into the console. 182 00:12:25,490 --> 00:12:28,070 So every single time this should print out true. 183 00:12:28,070 --> 00:12:28,970 And then one. 184 00:12:28,970 --> 00:12:32,090 And then next time it'll print true and the number two. 185 00:12:32,090 --> 00:12:38,000 And then the next time true and the number three and so on until our coroutine finishes executing in 186 00:12:38,000 --> 00:12:38,570 the for loop. 187 00:12:38,570 --> 00:12:40,160 And then we'll return finished. 188 00:12:40,160 --> 00:12:42,680 And the coroutine will be placed in a dead state. 189 00:12:43,100 --> 00:12:49,310 So let's go ahead and continue resuming our coroutine until our coroutine is placed in the dead state. 190 00:12:49,310 --> 00:12:53,990 And we can check that by using the coroutine dot status function. 191 00:12:53,990 --> 00:12:58,220 So we can pass our thread here, and it's going to return to us a string of what state it is in. 192 00:12:58,220 --> 00:13:00,080 So we can pass our thread here. 193 00:13:00,080 --> 00:13:03,620 And we can check to see if that is equal to the dead state. 194 00:13:03,620 --> 00:13:09,650 So we're only going to resume the coroutine as long as the status of the coroutine is not equal to the 195 00:13:09,650 --> 00:13:10,430 dead state. 196 00:13:10,880 --> 00:13:15,350 Now I also want to print out the status of our coroutine before we resume it. 197 00:13:15,350 --> 00:13:19,190 So we're going to do coroutine dot status and pass our thread. 198 00:13:19,190 --> 00:13:24,800 And every single time through the iteration of this repeat loop, this should print out suspended because 199 00:13:24,800 --> 00:13:27,290 we have not resumed our coroutine yet. 200 00:13:27,290 --> 00:13:28,760 And then we go and resume it. 201 00:13:28,760 --> 00:13:33,230 We print the result in the console, and then through the next iteration, it'll realize, oh, the 202 00:13:33,230 --> 00:13:34,610 coroutine is suspended again. 203 00:13:34,610 --> 00:13:40,040 Let's go ahead and resume it and get the next value and the next value until eventually we finish executing 204 00:13:40,040 --> 00:13:40,880 the coroutine. 205 00:13:40,880 --> 00:13:46,550 And then let's go ahead and print out a statement like coroutine is in a dead state. 206 00:13:47,620 --> 00:13:48,880 Now if we run our game. 207 00:13:50,490 --> 00:13:51,450 What are we going to get? 208 00:13:51,480 --> 00:13:52,410 Ooh, look at this. 209 00:13:52,410 --> 00:13:55,200 We get first print statement, which is suspended. 210 00:13:55,200 --> 00:13:57,450 Then we get our values of true and one. 211 00:13:57,450 --> 00:13:59,010 Then we get suspended again. 212 00:13:59,010 --> 00:13:59,310 True. 213 00:13:59,310 --> 00:14:01,770 And two, all the way up to five iterations. 214 00:14:01,770 --> 00:14:06,240 And then our coroutine reaches the end and it returns to us the message of finished. 215 00:14:06,240 --> 00:14:10,110 And our repeat loop realizes that our coroutine has been placed in a dead state. 216 00:14:10,110 --> 00:14:13,260 So it states coroutine is in a dead state. 217 00:14:13,960 --> 00:14:18,490 Now, let's say our coroutine encounters an error while it's executing this code up here. 218 00:14:18,490 --> 00:14:21,460 So I'm going to forcefully insert an error in here. 219 00:14:21,460 --> 00:14:23,140 I'm going to call the error function. 220 00:14:23,140 --> 00:14:27,370 And we'll just say a message like oh no, an error occurred. 221 00:14:30,260 --> 00:14:32,060 And then let's go ahead and run the game again. 222 00:14:33,140 --> 00:14:38,090 What you're going to see this time is that it's going to successfully loop through that entire for loop. 223 00:14:38,090 --> 00:14:43,160 But then right before we are able to reach the return statement inside of our function, it's going 224 00:14:43,160 --> 00:14:46,730 to print out false because the coroutine encountered an error. 225 00:14:46,730 --> 00:14:50,360 And it's going to tell us exactly what that coroutine error was. 226 00:14:50,360 --> 00:14:51,050 Oh no. 227 00:14:51,050 --> 00:14:53,840 An error occurred on line number five. 228 00:14:53,840 --> 00:15:00,140 And as you can see, it did not halt the execution of our game because the coroutine was protected and 229 00:15:00,140 --> 00:15:05,060 it still printed that the coroutine was placed in a dead state because the coroutine encountered an 230 00:15:05,060 --> 00:15:05,570 error. 231 00:15:06,180 --> 00:15:08,700 Let's go ahead and take a look at another example. 232 00:15:08,700 --> 00:15:14,310 For this example, I want to grab the current coroutine that is executing the code in my script. 233 00:15:14,310 --> 00:15:19,500 And remember we can do that by using the coroutine running function which returns the current running 234 00:15:19,500 --> 00:15:20,220 coroutine. 235 00:15:20,220 --> 00:15:22,350 So let's store that in a variable. 236 00:15:22,350 --> 00:15:24,300 We'll call it current coroutine. 237 00:15:24,930 --> 00:15:29,940 And then what I want to do is I want to force this coroutine to yield and then resume it later. 238 00:15:29,940 --> 00:15:33,630 And in order to do that we're going to need to have two separate coroutines. 239 00:15:33,630 --> 00:15:38,040 The separate one is going to resume it after some arbitrary amount of time. 240 00:15:38,580 --> 00:15:44,700 So what we can go ahead and do is call coroutine dot yield, which is going to force the coroutine currently 241 00:15:44,700 --> 00:15:46,230 executing the script to yield. 242 00:15:46,230 --> 00:15:50,580 But before we yield it, let's go ahead and have another function above. 243 00:15:50,580 --> 00:15:55,530 Wait for some random amount of time and then resume it again, which means we'll be able to execute 244 00:15:55,530 --> 00:15:58,080 any code after the coroutine dot yield call. 245 00:15:58,080 --> 00:16:02,130 So we could print something like coroutine was resumed. 246 00:16:03,350 --> 00:16:07,880 And for this example, let's go ahead and take a look at the coroutine dot wrap function. 247 00:16:07,880 --> 00:16:10,970 And for the wrap function we need to pass a function to it. 248 00:16:10,970 --> 00:16:12,800 So let's create a function. 249 00:16:13,490 --> 00:16:18,530 And inside of here what we're going to do is we're going to wait for a random amount of time let's say 250 00:16:18,530 --> 00:16:19,580 five seconds. 251 00:16:19,670 --> 00:16:23,870 And then we're going to use the coroutine dot resume function to. 252 00:16:24,480 --> 00:16:26,730 Resume our current coroutine. 253 00:16:27,370 --> 00:16:32,470 And then this is going to return to us a another function we'll call this wrapped function. 254 00:16:32,770 --> 00:16:37,210 And then to start this coroutine up here we need to call this function. 255 00:16:37,210 --> 00:16:39,100 So we'll refer to wrap function. 256 00:16:39,100 --> 00:16:40,450 And then we'll just call it. 257 00:16:40,480 --> 00:16:44,050 Now what's going to happen is the current thread is going to go in here. 258 00:16:44,050 --> 00:16:48,100 It's going to start executing this separate coroutine thread right here. 259 00:16:48,100 --> 00:16:50,170 It's going to encounter this yield statement. 260 00:16:50,170 --> 00:16:52,150 So it's going to leave this coroutine. 261 00:16:52,150 --> 00:16:53,740 And then it'll come back. 262 00:16:53,740 --> 00:16:59,020 And then it'll hit our yield statement here which is going to force the rest of our script to pause. 263 00:16:59,290 --> 00:17:04,240 And then after this five seconds is up, then it's going to resume that current coroutine that we just 264 00:17:04,240 --> 00:17:04,720 paused. 265 00:17:04,720 --> 00:17:05,710 And then we'll see. 266 00:17:05,710 --> 00:17:09,790 The message of coroutine was resumed printed back in the console. 267 00:17:09,910 --> 00:17:14,650 Now I also want to demonstrate that we can go ahead and pass values to the resume function. 268 00:17:14,650 --> 00:17:18,760 As you can see, there are three dots here telling us that we can pass whatever values we want. 269 00:17:18,760 --> 00:17:26,410 So let's pass a message and say something like I have resumed you from. 270 00:17:27,760 --> 00:17:29,650 Your friendly coroutine. 271 00:17:29,650 --> 00:17:33,850 So this is our message that we want to give back to the other coroutine. 272 00:17:34,210 --> 00:17:39,910 And what's going to happen is that this message is going to be given back to this function here. 273 00:17:40,090 --> 00:17:43,120 And we can store that inside of a variable. 274 00:17:43,120 --> 00:17:44,380 We'll just call it message. 275 00:17:44,380 --> 00:17:47,860 And then let's print that message out in the console. 276 00:17:49,110 --> 00:17:54,900 So if you remember what we read in the documentation, is that any time a coroutine encounters a coroutine 277 00:17:54,900 --> 00:17:58,320 dot yield function call, it's going to pause right here. 278 00:17:58,320 --> 00:18:05,910 And then any time another coroutine resumes it, it is able to pass other information back to this coroutine 279 00:18:05,910 --> 00:18:06,900 dot yield function call. 280 00:18:06,900 --> 00:18:12,600 So this when we call this is going to return back whatever was passed to the coroutine dot resume function. 281 00:18:12,600 --> 00:18:14,970 In that case it's going to be our message. 282 00:18:15,420 --> 00:18:17,040 So let's go ahead and run the game. 283 00:18:18,840 --> 00:18:22,740 And so far nothing is being printed, which is what we would expect. 284 00:18:22,740 --> 00:18:23,640 And then there we go. 285 00:18:23,640 --> 00:18:25,830 It says coroutine was resumed. 286 00:18:25,830 --> 00:18:29,820 The message is I have resumed you from your friendly coroutine. 287 00:18:30,300 --> 00:18:32,310 And actually, let's demonstrate this again. 288 00:18:32,310 --> 00:18:40,320 Before we yield, let's go ahead and print a message that the current coroutine is about to be paused. 289 00:18:41,030 --> 00:18:44,900 Then we'll pause it and then five seconds later we will resume it. 290 00:18:44,900 --> 00:18:46,220 So let's try this again. 291 00:18:47,210 --> 00:18:48,350 We'll get our message. 292 00:18:48,350 --> 00:18:50,690 Coroutine is about to be paused. 293 00:18:50,690 --> 00:18:51,890 And now we're waiting. 294 00:18:51,890 --> 00:18:52,760 And there we go. 295 00:18:52,760 --> 00:18:57,170 Five seconds later it says coroutine was resumed and then we get our message. 296 00:18:57,170 --> 00:18:58,010 Very cool. 297 00:18:58,400 --> 00:19:03,380 Now, something important I want to note is that the function returned by our coroutine dot wrap function 298 00:19:03,380 --> 00:19:08,990 is not protected from errors like a regular coroutine thread is, and that's because the wrap function 299 00:19:08,990 --> 00:19:12,020 is just returning a regular function to us. 300 00:19:12,550 --> 00:19:15,700 So to demonstrate this, let's go ahead and delete what we currently have. 301 00:19:15,700 --> 00:19:17,680 And let's create another wrapped function. 302 00:19:17,680 --> 00:19:19,420 So we'll call coroutine dot wrap. 303 00:19:19,420 --> 00:19:24,040 Pass a function here inside of this function I'm just going to force an error. 304 00:19:24,040 --> 00:19:26,110 And we could just say some error. 305 00:19:26,740 --> 00:19:31,990 And then I'm also going to put a return statement down here and return some value like we'll say Bobby. 306 00:19:32,560 --> 00:19:35,740 And then we can go ahead and store our wrapped function in a variable. 307 00:19:36,770 --> 00:19:41,780 And let's go ahead and see if we can print out the return value from our wrapped function. 308 00:19:41,780 --> 00:19:45,290 So when we call it, what's going to happen is we're going to hit this error. 309 00:19:45,290 --> 00:19:51,380 And since coroutine dot wrapped does not have any protection against errors, the entire coroutine that 310 00:19:51,380 --> 00:19:56,270 is executing inside of our script is going to halt, and it's going to print out an error message inside 311 00:19:56,270 --> 00:19:57,230 of the console. 312 00:19:57,230 --> 00:20:01,190 And that means we're not going to be able to reach our return statement of Bobby. 313 00:20:01,190 --> 00:20:04,730 So if we run the game and we take a look, there we go. 314 00:20:04,730 --> 00:20:08,540 We get our error on line number six and it says some error. 315 00:20:08,540 --> 00:20:13,670 And that's back to our code or our function on line number two. 316 00:20:14,240 --> 00:20:18,140 So as you can see it did not return a true or false boolean. 317 00:20:18,140 --> 00:20:21,170 And it did not return to us an error message as a string. 318 00:20:21,170 --> 00:20:24,650 And that's because they are not protected against errors. 319 00:20:24,650 --> 00:20:30,140 Now if I go ahead and delete this error message, then when I call my wrapped function, I should get 320 00:20:30,140 --> 00:20:32,540 Bobby printed inside of the console. 321 00:20:32,540 --> 00:20:35,660 So if we run the game, let's take a look. 322 00:20:35,660 --> 00:20:36,260 There we go. 323 00:20:36,260 --> 00:20:37,550 We get Bobby. 324 00:20:37,910 --> 00:20:43,610 Now you should also notice we did not get a boolean because once again wrapped functions are not protected 325 00:20:43,610 --> 00:20:44,810 against errors. 326 00:20:45,320 --> 00:20:48,110 Hopefully you're starting to get the hang of coroutines. 327 00:20:48,110 --> 00:20:51,200 So let's go ahead and look at another example. 328 00:20:51,650 --> 00:20:53,870 What I'm going to do is I'm going to create a function. 329 00:20:53,870 --> 00:20:56,750 I'm going to call this function repeat string. 330 00:20:56,750 --> 00:20:58,790 And we're going to pass a string to it. 331 00:20:58,790 --> 00:20:59,960 We'll just call it a word. 332 00:20:59,960 --> 00:21:07,400 Now what I want this function to do is I want it to continually repeat whatever word was passed here 333 00:21:07,400 --> 00:21:08,540 over and over and over again. 334 00:21:08,540 --> 00:21:09,620 So for example. 335 00:21:10,090 --> 00:21:16,720 If we get past the word of Bob, then we want to concatenate it with another word of Bob and then another 336 00:21:16,720 --> 00:21:17,260 one. 337 00:21:17,260 --> 00:21:19,210 So on for infinity. 338 00:21:19,210 --> 00:21:21,610 And we want to do this with coroutines of mine. 339 00:21:21,610 --> 00:21:24,190 So we can go ahead and do is have a while loop down here. 340 00:21:24,610 --> 00:21:29,770 And what we're going to do is we're going to continually concatenate this word together to get a bigger 341 00:21:29,770 --> 00:21:32,080 and bigger and bigger repeating word. 342 00:21:32,320 --> 00:21:38,350 Now I also want to go ahead and pass this function to our coroutine dot create function. 343 00:21:38,830 --> 00:21:43,540 So we'll pass repeat string to this, which is going to give us a brand new coroutine thread. 344 00:21:43,540 --> 00:21:49,660 And because this is now executing in its own coroutine thread, we are able to call the coroutine dot 345 00:21:49,690 --> 00:21:51,820 yield function and get a result. 346 00:21:51,820 --> 00:21:55,750 In this case, we want to get our word that has been concatenated together. 347 00:21:55,750 --> 00:21:57,400 So let's go ahead and create another variable. 348 00:21:57,400 --> 00:21:58,840 We'll call this repeated. 349 00:21:58,840 --> 00:22:04,180 And for now I'm going to set it to an empty string because inside of our while loop through every single 350 00:22:04,180 --> 00:22:09,130 iteration, we're going to update the value inside of here to be concatenated to itself. 351 00:22:09,130 --> 00:22:13,060 So we'll set repeated equal to repeated concatenated with our word. 352 00:22:13,060 --> 00:22:16,990 And it's going to keep doing this through every iteration of our loop, which is going to give us a 353 00:22:16,990 --> 00:22:19,480 bigger and bigger word that has been repeating. 354 00:22:19,480 --> 00:22:21,640 Now another way we can do this that is quicker. 355 00:22:21,640 --> 00:22:27,490 We can use the dot dot equal operator, which does the exact same thing of what we just saw right here. 356 00:22:27,490 --> 00:22:30,010 It's just more concise syntax. 357 00:22:30,010 --> 00:22:36,040 But now what we need to go ahead and do is we need to start the execution of our coroutine thread. 358 00:22:36,040 --> 00:22:39,820 So let's go ahead and call the coroutine dot resume function. 359 00:22:40,420 --> 00:22:42,280 And we're going to pass our thread here. 360 00:22:42,280 --> 00:22:45,340 And then we also need to pass other information to our thread. 361 00:22:45,340 --> 00:22:47,860 In this case that is going to be our word. 362 00:22:47,860 --> 00:22:50,650 So what word would we like to repeat. 363 00:22:50,650 --> 00:22:54,040 Well let's go ahead and repeat the word of Bob. 364 00:22:54,790 --> 00:22:58,060 And then we're able to print what gets returned from here. 365 00:22:58,060 --> 00:23:04,480 Because what we're going to do is when we call our coroutine dot yield function, let's pass this repeated 366 00:23:04,480 --> 00:23:05,050 word. 367 00:23:05,050 --> 00:23:10,270 So that means it's going to return our word back to the coroutine dot resume function call. 368 00:23:10,270 --> 00:23:13,240 And we should be able to print it inside of the console. 369 00:23:13,240 --> 00:23:17,920 So if we run our game, what we're going to see inside of the console is true. 370 00:23:17,920 --> 00:23:19,810 And then there's our word Bob. 371 00:23:19,810 --> 00:23:25,480 So through the first iteration of our while loop, of course there's only going to be one bob concatenated 372 00:23:25,480 --> 00:23:26,890 to our empty string. 373 00:23:26,890 --> 00:23:30,730 But let's say we copy this and do it again. 374 00:23:30,730 --> 00:23:36,310 But this time we don't actually need to put Bob right here, because it's already going to have the 375 00:23:36,310 --> 00:23:38,980 word inside of our thread. 376 00:23:38,980 --> 00:23:41,830 We're just resuming it again because it hit that yield statement. 377 00:23:41,830 --> 00:23:46,390 So it's going to go through the next iteration of the loop and concatenate it again and then return 378 00:23:46,390 --> 00:23:47,290 that back to us. 379 00:23:47,290 --> 00:23:49,000 So this should print Bob. 380 00:23:49,000 --> 00:23:53,290 Bob, if we run the game we should get Bob. 381 00:23:53,290 --> 00:23:54,130 And there we go Bob. 382 00:23:54,130 --> 00:23:54,610 Bob. 383 00:23:55,190 --> 00:23:59,510 Well, what if we resume the thread again and again and again? 384 00:23:59,540 --> 00:24:01,130 Let's see what happens this time. 385 00:24:01,850 --> 00:24:06,230 Now we're going to get Bob, Bob, Bob, Bob Bob Bob Bob Bob Bob. 386 00:24:06,380 --> 00:24:11,420 You see, it's concatenating Bob every single time we are resuming that coroutine thread. 387 00:24:11,420 --> 00:24:13,790 So actually let's do something a little bit different here. 388 00:24:14,290 --> 00:24:20,380 Let's create a for loop that iterates, let's say 50 times. 389 00:24:20,590 --> 00:24:23,530 And all we're going to do is just resume. 390 00:24:24,300 --> 00:24:25,320 This coroutine. 391 00:24:25,320 --> 00:24:26,460 So coroutine dot resume. 392 00:24:26,460 --> 00:24:27,570 Pass our thread here. 393 00:24:27,570 --> 00:24:33,420 So now we should have Bob Bob Bob printing out 50 different times inside of our console getting bigger 394 00:24:33,420 --> 00:24:34,590 every single time. 395 00:24:34,590 --> 00:24:37,080 So let's run it and see what happens. 396 00:24:37,740 --> 00:24:38,940 Oh there we go. 397 00:24:38,940 --> 00:24:40,890 We get our 50 print statements. 398 00:24:40,890 --> 00:24:47,970 First iteration is Bob, then Bob, Bob, so on and so forth as it continues to concatenate Bob to itself. 399 00:24:47,970 --> 00:24:52,050 And we just have this giant triangle of bob strings. 400 00:24:53,110 --> 00:24:53,590 All right. 401 00:24:53,590 --> 00:24:56,230 So that was a lot of information to digest. 402 00:24:56,230 --> 00:25:00,910 And hopefully you now understand the coroutine library and the thread data type. 403 00:25:00,910 --> 00:25:06,130 If you would like to learn more about coroutines I'll leave a resource attached to this lecture that 404 00:25:06,130 --> 00:25:10,360 goes to the official Lua documentation, which details coroutines in depth. 405 00:25:10,360 --> 00:25:15,910 In the future, however, we will be taking a look at something called the Task Library, which you 406 00:25:15,910 --> 00:25:19,630 will likely be using much more often than coroutines in your scripts. 407 00:25:19,630 --> 00:25:23,470 Otherwise, thanks for watching and I'll see you in the next lecture.